home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / program / ixemlsrc.lha / ixemul / stdlib / exec.c < prev    next >
C/C++ Source or Header  |  1995-12-23  |  6KB  |  234 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #if defined(LIBC_SCCS) && !defined(lint)
  35. static char sccsid[] = "@(#)exec.c    5.9 (Berkeley) 6/17/91";
  36. #endif /* LIBC_SCCS and not lint */
  37.  
  38. #define KERNEL
  39. #include "ixemul.h"
  40. #include "kprintf.h"
  41.  
  42. #include <errno.h>
  43. #include <unistd.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <paths.h>
  47.  
  48. #ifdef __STDC__
  49. #include <stdarg.h>
  50. #else
  51. #include <varargs.h>
  52. #endif
  53.  
  54. static char **
  55. buildargv(ap, arg, envpp)
  56.     va_list ap;
  57.     const char *arg;
  58.     char ***envpp;
  59. {
  60.     register size_t max, off;
  61.     register char **argv = NULL;
  62.  
  63.     for (off = max = 0;; ++off) {
  64.         if (off >= max) {
  65.             max += 50;    /* Starts out at 0. */
  66.             max *= 2;    /* Ramp up fast. */
  67.             if (!(argv = realloc(argv, max * sizeof(char *))))
  68.                 return(NULL);
  69.             if (off == 0) {
  70.                 argv[0] = (char *)arg;
  71.                 off = 1;
  72.             }
  73.         }
  74.         if (!(argv[off] = va_arg(ap, char *)))
  75.             break;
  76.     }
  77.     /* Get environment pointer if user supposed to provide one. */
  78.     if (envpp)
  79.         *envpp = va_arg(ap, char **);
  80.     return(argv);
  81. }
  82.  
  83. int execl(const char *name, const char *arg, ...)
  84. {
  85.     va_list ap;
  86.     int sverrno;
  87.     char **argv;
  88.  
  89.     va_start(ap, arg);
  90.     if ((argv = buildargv(ap, arg, (char ***)NULL)))
  91.         (void)execve(name, argv, *u.u_environ);
  92.     va_end(ap);
  93.     sverrno = errno;
  94.     free(argv);
  95.     errno = sverrno;
  96.     KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  97.     return(-1);
  98. }
  99.  
  100. int execle(const char *name, const char *arg, ...)
  101. {
  102.     va_list ap;
  103.     int sverrno;
  104.     char **argv, **envp;
  105.  
  106.     va_start(ap, arg);
  107.     if ((argv = buildargv(ap, arg, &envp)))
  108.         (void)execve(name, argv, envp);
  109.     va_end(ap);
  110.     sverrno = errno;
  111.     free(argv);
  112.     errno = sverrno;
  113.     KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  114.     return(-1);
  115. }
  116.  
  117. int execlp(const char *name, const char *arg, ...)
  118. {
  119.     va_list ap;
  120.     int sverrno;
  121.     char **argv;
  122.  
  123.     va_start(ap, arg);
  124.     if ((argv = buildargv(ap, arg, (char ***)NULL)))
  125.         (void)execvp(name, argv);
  126.     va_end(ap);
  127.     sverrno = errno;
  128.     free(argv);
  129.     errno = sverrno;
  130.     KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  131.     return(-1);
  132. }
  133.  
  134. int execv(const char *name, char * const *argv)
  135. {
  136.     execve(name, argv, *u.u_environ);
  137.     return(-1);
  138. }
  139.  
  140. int execvp(const char *name, char * const *argv)
  141. {
  142.     register int lp, ln;
  143.     register char *p;
  144.     int eacces, etxtbsy;
  145.     char *bp, *cur, *path, buf[MAXPATHLEN];
  146.  
  147.     eacces = etxtbsy = 0;
  148.     /* If it's an absolute or relative path name, it's easy. */
  149.     if (index(name, '/') || index (name, ':')) {
  150.         bp = (char *)name;
  151.         cur = path = NULL;
  152.         goto retry;
  153.     }
  154.     bp = buf;
  155.  
  156.     /* first try to call execve() without path lookup. execve() walks
  157.        a (possibly provided) CLI PATH, and also supports resident
  158.        programs. If this fails, we can still try to find the program
  159.        along the $PATH */
  160.     execv (name, argv);
  161.     /* if we get here, the execv() failed. So start magic ;-)) */
  162.  
  163.     /* Get the path we're searching. */
  164.     if (!(path = getenv("PATH")))
  165.         path = _PATH_DEFPATH;
  166.     cur = path = strdup(path);
  167.  
  168.     while ((p = strsep(&cur, ",:"))) {
  169.         /*
  170.          * It's a SHELL path -- double, leading and trailing colons
  171.          * mean the current directory.
  172.          */
  173.         if (!*p) {
  174.             p = ".";
  175.             lp = 1;
  176.         } else
  177.             lp = strlen(p);
  178.         ln = strlen(name);
  179.  
  180.         /*
  181.          * If the path is too long complain.  This is a possible
  182.          * security issue; given a way to make the path too long
  183.          * the user may execute the wrong program.
  184.          */
  185.         if (lp + ln + 2 > sizeof(buf)) {
  186.             syscall(SYS_write, STDERR_FILENO, "execvp: ", 8);
  187.             syscall(SYS_write, STDERR_FILENO, p, lp);
  188.             syscall(SYS_write, STDERR_FILENO, ": path too long\n", 16);
  189.             continue;
  190.         }
  191.         bcopy(p, buf, lp);
  192.         buf[lp] = '/';
  193.         bcopy(name, buf + lp + 1, ln);
  194.         buf[lp + ln + 1] = '\0';
  195.  
  196. retry:        execve(bp, argv, *u.u_environ);
  197.         switch(errno) {
  198.         case EACCES:
  199.             eacces = 1;
  200.             break;
  201.         case ENOENT:
  202.             break;
  203.         case ENOEXEC: {
  204.             register size_t cnt;
  205.             register char **ap;
  206.  
  207.             for (cnt = 0, ap = (char **)argv; *ap; ++ap, ++cnt);
  208.             if ((ap = malloc((cnt + 2) * sizeof(char *)))) {
  209.                 bcopy(argv + 1, ap + 2, cnt * sizeof(char *));
  210.                 ap[0] = "sh";
  211.                 ap[1] = bp;
  212.                 execve(_PATH_BSHELL, ap, *u.u_environ);
  213.                 free(ap);
  214.             }
  215.             goto done;
  216.         }
  217.         case ETXTBSY:
  218.             if (etxtbsy < 3)
  219.                 sleep(++etxtbsy);
  220.             goto retry;
  221.         default:
  222.             goto done;
  223.         }
  224.     }
  225.     if (eacces)
  226.         errno = EACCES;
  227.     else if (!errno)
  228.         errno = ENOENT;
  229.     KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  230. done:    if (path)
  231.         free(path);
  232.     return(-1);
  233. }
  234.